package tiled.core;

import java.awt.Rectangle;
import java.awt.geom.Area;
import java.util.Properties;

public abstract class MapLayer implements Cloneable
{
    public static final int MIRROR_HORIZONTAL = 1;
    public static final int MIRROR_VERTICAL = 2;

    public static final int ROTATE_90 = 90;
    public static final int ROTATE_180 = 180;
    public static final int ROTATE_270 = 270;

    protected String name;
    protected boolean isVisible = true;
    protected boolean bLocked = false;
    protected Map myMap;
    protected float opacity = 1.0f;
    protected Rectangle bounds;
    private Properties properties;

    public MapLayer()
    {
        bounds = new Rectangle();
        setMap(null);
        properties = new Properties();
    }

    public MapLayer(int w, int h)
    {
        this(new Rectangle(0, 0, w, h));
    }

    public MapLayer(Rectangle r)
    {
        this();
        setBounds(r);
    }

    MapLayer(Map map)
    {
        this();
        setMap(map);
    }

    public MapLayer(Map map, int w, int h)
    {
        this(w, h);
        setMap(map);
    }

    public void translate(int dx, int dy)
    {
        bounds.x += dx;
        bounds.y += dy;
    }

    public abstract void rotate(int angle);

    public abstract void mirror(int dir);

    protected void setBounds(Rectangle bounds)
    {
        this.bounds = new Rectangle(bounds);
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public void setMap(Map map)
    {
        myMap = map;
    }

    public void setOpacity(float opacity)
    {
        if (this.opacity != opacity)
        {
            this.opacity = opacity;

            if (isVisible() && myMap != null)
            {
                myMap.fireMapChanged();
            }
        }
    }

    public void setVisible(boolean visible)
    {
        if (isVisible != visible)
        {
            isVisible = visible;
            if (myMap != null)
            {
                myMap.fireMapChanged();
            }
        }
    }

    public void setOffset(int xOff, int yOff)
    {
        bounds.x = xOff;
        bounds.y = yOff;
    }

    public String getName()
    {
        return name;
    }

    public int getWidth()
    {
        return bounds.width;
    }

    public int getHeight()
    {
        return bounds.height;
    }

    public Rectangle getBounds()
    {
        return new Rectangle(bounds);
    }

    public void getBounds(Rectangle rect)
    {
        rect.setBounds(bounds);
    }

    public boolean contains(int x, int y)
    {
        return bounds.contains(x, y);
    }

    public float getOpacity()
    {
        return opacity;
    }

    public boolean isVisible()
    {
        return isVisible;
    }

    public abstract void mergeOnto(MapLayer other);

    public abstract void maskedMergeOnto(MapLayer other, Area mask);

    public abstract void copyFrom(MapLayer other);

    public abstract void maskedCopyFrom(MapLayer other, Area mask);

    public abstract MapLayer createDiff(MapLayer ml);

    public abstract void copyTo(MapLayer other);

    public abstract boolean isEmpty();

    public Object clone() throws CloneNotSupportedException
    {
        MapLayer clone = (MapLayer)super.clone();

        clone.bounds = new Rectangle(bounds);
        clone.properties = (Properties)properties.clone();
        
        return clone;
    }

    public abstract void resize(int width, int height, int dx, int dy);

    public boolean getLocked()
    {
        return bLocked;
    }

    public void setLocked(boolean lock)
    {
        bLocked = lock;
    }

    public void setProperties(Properties p)
    {
        properties = p;
    }

    public Properties getProperties()
    {
        return properties;
    }

    public boolean canEdit()
    {
        return !getLocked() && isVisible();
    }
}
